﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using WindGoes6.Data;
using WindGoes6.Database;

namespace WindGoes6.Forms
{
    /// <summary>
    /// 用于MSS数据库连接测试的窗体。
    /// </summary>
    public partial class ConnectionVerificationForm : Form
    {
        /// <summary>
        /// 保存的文件路径。
        /// </summary>
        public static string FilePath { get; set; } = "connection.txt";

        /// <summary> 
        /// 连接字符串对象。
        /// </summary>
        public SQLConnection Connection { get; set; }

        /// <summary>
        /// 当前窗体是否已经连接成功。
        /// </summary>
        public bool Connected { get; set; }


        /// <summary>
        /// 是否保存连接信息到本地，为True时会记录每次连接成功的字符串。
        /// </summary>
        public bool IsLocalSave = true;


        // 用于保存已经存在的数据库连接字符串信息。
        List<SQLConnection> cms = new List<SQLConnection>();

        // 用于记录连接时间
        DateTime startTime;

        /// <summary>
        /// 无参构造函数。
        /// </summary>
        public ConnectionVerificationForm()
        {
            InitializeComponent();
        }

        /// 当前选择的连接
        private SQLConnection GetCurrentConnection()
        {
            return cbServer.SelectedIndex >= 0 && cbServer.SelectedIndex < cbServer.Items.Count ? cms[cbServer.SelectedIndex] : null;
        }

        /// <summary>
        /// 向窗体添加连接字符串。
        /// </summary>
        /// <param name="constr">连接字符串。</param>
        public void AddConnectionString(string constr)
        {
            SQLConnection sm = SQLConnection.FromDesString(constr, true);
            if (sm != null && sm.DataSource != null)
            {
                try
                {
                    cbServer.Items.Add(sm.DataSource);
                    cms.Add(sm);
                }
                catch { }
            }
        }

        private void rbLocalDB_CheckedChanged(object sender, EventArgs e)
        {
            txtUserName.Enabled = rbRemoteDB.Checked;
            txtPassword.Enabled = rbRemoteDB.Checked;
        }

        private void rbRemoteDB_CheckedChanged(object sender, EventArgs e)
        {
            txtUserName.Enabled = rbRemoteDB.Checked;
            txtPassword.Enabled = rbRemoteDB.Checked;
        }

        private void cbServer_SelectedIndexChanged(object sender, EventArgs e)
        {
            Connection = GetCurrentConnection();
            if (Connection.TrustedConnection)
            {
                rbLocalDB.Checked = true;
            }
            else
            {
                rbRemoteDB.Checked = true;
                txtUserName.Text = Connection.UserID;
                txtPassword.Text = Connection.Password; 
                cbDatabase.Text = Connection.InitialCatalog;
            }
        }

        private void cbDatabase_SelectedIndexChanged(object sender, EventArgs e)
        {
            btnSave.Enabled = cbDatabase.SelectedIndex >= 0;
        }

        private void btnConnectionTest_Click(object sender, EventArgs e)
        {
            btnConnectionTest.Enabled = false;
            lblResult.Text = "连接测试中";
            startTime = DateTime.Now;
            Connection = GetConnectionFromUI();
            timer1.Start();

            MultiThreadSqlCon mt = new MultiThreadSqlCon(Connection.ConnectionString, (int)numericUpDown1.Value);
            mt.AfterTest += new MyEvent(mt_AfterTest);
            mt.StartTest();
        }

        private SQLConnection GetConnectionFromUI()
        {
            string db = cbDatabase.Text.Length > 0 ? cbDatabase.Text : "master";
            return rbLocalDB.Checked ?
                        new SQLConnection(cbServer.Text, db) :
                        new SQLConnection(cbServer.Text, db, txtUserName.Text, txtPassword.Text);
        }

        void mt_AfterTest(bool result, Exception e)
        {
            timer1.Stop();
            btnConnectionTest.Enabled = true;
            Connected = result;
            lblTotalTime.Text = numericUpDown1.Value.ToString("总时间：0.0s");
            if (Connected)
            {
                cbDatabase.Enabled = true;
                cbDatabase.Items.Clear();
                cbDatabase.Items.AddRange(GetAllDataBase(Connection.ConnectionString).ToArray());

                if (cms.Count(c => c.DataSource == Connection.DataSource) == 0)
                {
                    cms.Add(Connection);
                    cbServer.Items.Add(Connection.DataSource);
                }
                SaveConnections();
            }

            var info = Connected ? "数据库连接成功!" : "数据库连接失败，原因如下：\n" + e.Message;
            MessageBox.Show(info, "测试完成", MessageBoxButtons.OK, Connected ? MessageBoxIcon.Information : MessageBoxIcon.Error);
        }

        /// <summary>
        /// 保存所有连接。
        /// </summary>
        private void SaveConnections()
        {
            if (IsLocalSave)
            {
                using (StreamWriter sw = new StreamWriter(FilePath, false, Encoding.UTF8))
                {
                    foreach (var conn in cms)
                        sw.WriteLine(conn.ToDESString(true));
                }
            }
        }

        private List<string> GetAllDataBase(string con)
        {
            SQLManager sm = new SQLManager(con);
            sm.CommandText = "select name from master..sysdatabases";
            string[] data = sm.GetColumn();
            string[] exclusiveNames = { "master", "tempdb", "model", "msdb" };
            List<string> list = new List<string>();
            for (int i = 0; i < data.Length; i++)
                if (!exclusiveNames.Contains(data[i].ToLower()))
                    list.Add(data[i]);
            return list;
        }

        private void ConnectionVerificationForm_Load(object sender, EventArgs e)
        {
            if (IsLocalSave && File.Exists(FilePath))
            {
                foreach (var row in File.ReadAllLines(FilePath, Encoding.UTF8))
                {
                    var con = SQLConnection.FromDesString(row, true);
                    if (con != null)
                    {
                        cms.Add(con);
                        cbServer.Items.Add(con.DataSource);
                    }
                }
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            lblTotalTime.Text = (DateTime.Now - startTime).TotalSeconds.ToString("总时间：0.0s");
            lblResult.Text = lblResult.Text == "连接测试中..." ? "连接测试中" : lblResult.Text + ".";
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (cbDatabase.Text.Length == 0 && MessageBox.Show("确认选择数据库名称。", "数据库选择确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
                return;
            SaveConnections();
            Close();
        }
    }
}
